package com.ctrip.corp.obt.shard.sql.mybatis.interceptor.compatibility;

import com.ctrip.corp.obt.generic.utils.CollectionUtils;
import com.ctrip.corp.obt.shard.sql.parser.AbstractSqlParserSupport;
import com.google.common.collect.Lists;
import lombok.Data;
import net.sf.jsqlparser.expression.Function;
import net.sf.jsqlparser.expression.LongValue;
import net.sf.jsqlparser.expression.operators.relational.ExpressionList;

import java.util.Map;
import java.util.Objects;

/**
 * 描述
 *
 * @author x.shen
 * @since 2024/5/6
 */
public abstract class BaseFunctionCompatibility extends AbstractSqlParserSupport {

    @Data
    public static class SubFunction {
        /**
         * 需要替换的函数名
         */
        private String name;
        /**
         * 函数()中的值可能存在的前缀
         */
        private String prefix;
        /**
         * 替换的函数()中的值
         */
        private ExpressionList parameters;

        public SubFunction(String name) {
            this.name = name;
        }

        public SubFunction(String name, String prefix) {
            this.name = name;
            this.prefix = prefix;
        }

        public SubFunction(String name, Long params) {
            this.name = name;
            this.parameters = new ExpressionList(Lists.newArrayList(new LongValue(params)));
        }
    }

    /**
     * 通用函数兼容
     * 
     * @param expression 原函数表达式
     * @param sqlFunctionMap
     */
    public void handleCommonFunction(Function expression, Map<String, SubFunction> sqlFunctionMap) {
        if (CollectionUtils.isEmpty(sqlFunctionMap)) {
            return;
        }
        // 转小写
        String functionName = expression.getName().toLowerCase();
        SubFunction value = sqlFunctionMap.get(functionName);
        if (Objects.nonNull(value)) {
            expression.setName(value.getName());
            // 部分函数是需要有入参的 如now(3)，部分参数是不需要入参的，也有部分参数是需要保持入参为原样的
            if (Objects.nonNull(value.getParameters())) {
                expression.setParameters(value.getParameters());
            }
        }
    }

    /**
     * 特殊函数处理
     *
     * @param expression
     */
    public abstract void handleSpecialFunction(Function expression);
}
